package main

import (
	"fmt"
	"sync"
	"time"
)

// 使用WaitGroup的goroutine会等待预设好数量的goroutine都提交执行结束后，才会继续往下执行代码
// 在goroutine调用WaitGroup之前我们需要保证WaitGroup中等待数量大于1
// 保证WaitGroup.Done()执行的次数与WaitGroup.Add()相同，过少会导致等待goroutine死锁，过多导致panic
func main() {

	var wg sync.WaitGroup

	for i := 1; i <= 5; i++ {
		//Add 方法用于增加需要等待的 goroutine 数量。通常在启动新的 goroutine 之前调用此方法。
		wg.Add(1)
		go func(i int) {
			//Done 方法用于表示一个 goroutine 已经完成工作。每次调用 Done 方法时，WaitGroup 的计数器值会减少 1。
			defer wg.Done()
			fmt.Println("func", i, "get lock", time.Now().Format("2006-01-02 15:04:05"))
			time.Sleep(time.Second)
			fmt.Println("func", i, "release lock", time.Now().Format("2006-01-02 15:04:05"))
		}(i)
	}
	//Wait 方法会阻塞当前 goroutine，直到 WaitGroup 的计数器值变为 0，即所有被等待的 goroutine 都已完成。
	wg.Wait()
	fmt.Println("over", time.Now().Format("2006-01-02 15:04:05"))

}
func test() {
	var wg sync.WaitGroup
	//Add 方法用于增加需要等待的 goroutine 数量。通常在启动新的 goroutine 之前调用此方法。
	wg.Add(5)
	for i := 1; i <= 5; i++ {
		go func(i int) {
			//Done 方法用于表示一个 goroutine 已经完成工作。每次调用 Done 方法时，WaitGroup 的计数器值会减少 1。
			defer wg.Done()
			fmt.Println("func", i, "get lock", time.Now().Format("2006-01-02 15:04:05"))
			time.Sleep(time.Second)
			fmt.Println("func", i, "release lock", time.Now().Format("2006-01-02 15:04:05"))
		}(i)
	}
	//Wait 方法会阻塞当前 goroutine，直到 WaitGroup 的计数器值变为 0，即所有被等待的 goroutine 都已完成。
	wg.Wait()
	fmt.Println("over", time.Now().Format("2006-01-02 15:04:05"))
}
